#include "erenderer.h"
#include "../resources/etexture.h"
#include "esprite.h"
#include "egraphicsobject.h"
#include "../animation/eanimationset.h"
#include "../animation/eanimation.h"
#include "../animation/eframedanimation.h"
#include "../eapplication.h"

#include <SDL_opengl.h>

ERenderer::ERenderer()
{
}

void ERenderer::renderSprite(boost::shared_ptr<ESprite> sprite, boost::shared_ptr<ETexture> texture,
                  QRect sourceRect)
{
    // TODO: for parent-child transformations, transform code should be moved to place in code marked as (1)
    QPointF pos = sprite->pos();
    float angle = sprite->angle();
    QPointF scale = sprite->scale();
    QPointF pivot = sprite->pivot();
    QColor color = sprite->color();
    float alpha = sprite->alpha();

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    // TODO: check if it has to be applied on trans and scale
    QPointF resolutionScale = EApplication::app().resoultionScale();

    glTranslatef(pos.x()*resolutionScale.x(), pos.y()*resolutionScale.y(), 0);

    // TODO: check pivot point dependence of resolutionScale (it is in local coords so
    // maybe there is no need to be dependent of resolution scale
    glTranslatef(pivot.x(), pivot.y(), 0);
    glRotatef(angle, 0, 0, 1.0f);
    glScalef(scale.x()*resolutionScale.x(), scale.y()*resolutionScale.y(), 1.0f);
    glTranslatef(-pivot.x(), -pivot.y(), 0);

    float left = -sourceRect.width()/2.0f;
    float right = sourceRect.width()/2.0f;
    float top = -sourceRect.height()/2.0f;
    float bottom = sourceRect.height()/2.0f;

    float vertices[] = { left, top,
                         right, top,
                         right, bottom,
                         left, bottom
                       };

    // calculate from source rect and texture rect
    float texCoords[] = { 0, 0,
                        1, 0,
                        1, 1,
                        0, 1
                      };

    glColor4f(color.red()/255.0f, color.green()/255.0f, color.blue()/255.0f, alpha);
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, texture->id());

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glVertexPointer(2, GL_FLOAT, 0, vertices);
    glTexCoordPointer(2, GL_FLOAT, 0, texCoords);

    glDrawArrays(GL_QUADS, 0, 4);

    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);

    glDisable(GL_BLEND);
}

void ERenderer::render(boost::shared_ptr<EGraphicsObject> go)
{
    boost::shared_ptr<ESprite> sprite = go->sprite();
    boost::shared_ptr<EAnimationSet> anims = go->anims();
    boost::shared_ptr<EFramedAnimation> currentAnim;
    QRect sourceRect;

    if(anims)
    {
        currentAnim = boost::static_pointer_cast<EFramedAnimation>(anims->currentAnimation());
    }

    boost::shared_ptr<ETexture> texture = currentAnim ? currentAnim->texture() : go->texture();

    sourceRect = currentAnim ? currentAnim->currentFrameRect() : QRect(0, 0, texture->width(), texture->height());

    // (1)
    glPushMatrix();
    renderSprite(sprite, texture, sourceRect);
    glPopMatrix();
}
